`ifndef _MEMORY_V
`define _MEMORY_V 1

`include "Defines.v"

module RegFile(RADDR1,DOUT1,RADDR2,DOUT2,WADDR1,DIN1, WADDR2, DIN2, WE1,WE2,CLK, LOCK);
  parameter DBITS; // Number of data bits
  parameter ABITS; // Number of address bits
  parameter WORDS = (1<<ABITS);
  parameter MFILE = "";
  (* ram_init_file = MFILE *)
  reg [(DBITS-1):0] mem[(WORDS-1):0];
  input  [(ABITS-1):0] RADDR1,RADDR2,WADDR1, WADDR2;
  input  [(DBITS-1):0] DIN1, DIN2;
  input wire LOCK;
  output wire [(DBITS-1):0] DOUT1,DOUT2;
  input CLK,WE1, WE2;
  always @(posedge CLK) if(LOCK) begin
    if(WE1) begin
      mem[WADDR1]=DIN1;
    end
    if(WE2)begin
	  mem[WADDR2]=DIN2;
	end
  end
  assign DOUT1=(WE1&&(WADDR1==RADDR1)) ? DIN1:
			   (WE2&&(WADDR2==RADDR1)) ? DIN2:
								mem[RADDR1];
  assign DOUT2=(WE1&&(WADDR1==RADDR2)) ? DIN1: 
			   (WE2&&(WADDR2==RADDR2)) ? DIN2:
								mem[RADDR2];
endmodule

module BranchTable(RADDR1,DOUT1,WADDR,DIN,WE,CLK,LOCK);
  parameter DBITS; // Number of data bits
  parameter ABITS; // Number of address bits
  parameter WORDS = (1<<ABITS);
  parameter MFILE = "";
  (* ram_init_file = MFILE *)
  reg [(DBITS-1):0] mem[(WORDS-1):0];
  input  [(ABITS-1):0] RADDR1,WADDR;
  input  [(DBITS-1):0] DIN;
  input wire LOCK;
  output wire [(DBITS-1):0] DOUT1;
  input CLK,WE;
  always @(posedge CLK)if(LOCK) begin
    if(WE)
      mem[WADDR]=DIN;
  end
  assign DOUT1=(WE&&(WADDR==RADDR1))?DIN:mem[RADDR1];
endmodule
//ASSIGN 5 MODULES INCLUDING NEW MEMORY

module Memory(IADDR,IOUT,ABUS,DBUS,WE,CLK,LOCK,INIT);
  // File to initialize memory with
  parameter MFILE;
  // Number of bits in a memory word
  parameter BITS;
  // Number of bits in the real address
  parameter RABITS;  
  parameter RWORDS=(1<<(RABITS-2));
  input wire [(BITS-1):0] IADDR,ABUS;
  output wire [(BITS-1):0] IOUT;
  inout wire [(BITS-1):0] DBUS;
  input wire WE,CLK,LOCK,INIT;
  // does address refer to actual memory
  wire selMem=(ABUS[(BITS-1):RABITS]=={(BITS-RABITS){1'b0}});
  // Will we write a memory location?
  wire wrMem=WE&&selMem;
  // Should we drive a value from memory to the bus?
  wire rdMem=(!WE)&&selMem;
  // Real memory
  (* ram_init_file = MFILE *) (* ramstyle="no_rw_check" *)
  reg [(BITS-1):0] marray[RWORDS];
  always @(posedge CLK) if(LOCK) begin
    if(INIT) begin
    end else begin
      if(wrMem)
        marray[ABUS[(RABITS-1):2]]<=DBUS;
    end
  end
  // This should be familiar
  assign DBUS=rdMem?marray[ABUS[(RABITS-1):2]]:
                    {BITS{1'bz}};
  // Instructions have their own read port that does not go to the data bus
  assign IOUT=
    (IADDR[(BITS-1):RABITS]=={(BITS-RABITS){1'b0}})?
    marray[IADDR[(RABITS-1):2]]:
    32'hDEADBEEF;
endmodule



`endif //_MEMORY_V
